home *** CD-ROM | disk | FTP | other *** search
/ Inside Mac Games Volume 3 #12 / IMG 33 Dec 1995.iso / Important Files / MGW1Codeƒ / ClamMusic.c next >
Text File  |  1995-11-14  |  27KB  |  635 lines

  1. //==============================================================================================\\
  2. //        -----------------------------------------------------------------------------------        \\
  3. //        ClamMusic.c version 1.0.0    copyright © 1993…1995 Jamie McCornack, john calhoun            \\
  4. //        -----------------------------------------------------------------------------------        \\
  5. //         Demo program for Macintosh GameWriter 1.0.0, a training program…                        \\
  6. //        …for beginning Mac game programmers. MGW1 includes MGWExterns1.h, MGWUtilities1.c,…        \\
  7. //        …MGWSound1.c, MGWGraphics1.c, MGWGraphicsBWLite1.c, HelloWorld.rsrc and an assortment…    \\
  8. //        …of demo programs; projects HelloWorld1.π etc. and source code files HelloWorld1.c etc.    \\
  9. //         A tutorial is available in Tricks of the Mac Game Programming Gurus, published…        \\
  10. //        …by Hayden Books, August 1995.                                                            \\
  11. //                                                                                                \\
  12. //        This code is offered by the copyright holders for no fee and for whatever use…            \\
  13. //        …you care to make of it, but we do hope you remember where it came from.                \\
  14. //                                                                                                \\
  15. //        Please send bug reports to MacGameDev at America OnLine.    macgamedev@aol.com            \\
  16. //        Suggestions and observations are also appreciated.                                        \\
  17. //        Updates and upgrades will be available now and then from the above e-mail address.        \\
  18. //==============================================================================================\\
  19.  
  20. // This program opens a window, displays an 8-bit color background, and at first…
  21. // …mouseclick, runs two clams across the screen. At second mouseclick, one clam stops,…
  22. // …talks, and flaps its/his/her face for 40 frames as the other clam continues running.
  23. // When the other clam runs up to the standing clam, there is an impact.
  24.  
  25. // If the monitor is not set to 8-bit, a soft alert is displayed, asking if the user…
  26. // …would like to switch to 8-bit, or stick with the current setting.
  27.  
  28. // It's just like HelloWorld8Bit except it has a little ditty playing in the background, as a…
  29. // …sequencing demonstration. About 135K of uncompressed sampled sound gives us a minute-plus…
  30. // …of music, as opposed to 727K for 30 seconds when played as a single 'snd ' resource.
  31.  
  32. // The music clips were sampled from InfoHiway1, courtesy of Optical Media International.
  33.  
  34.  
  35. #include "MGWExterns1.h"
  36.  
  37. #define     kPutInFront    (WindowPtr)-1L
  38. #define     kWaitTicks     4L        // Sets the delay in Ticks between frames. Try 3. Try 2. Try 0.
  39. #define     kJaneStepLength    12    // Sets the distance in pixels between Clamity Jane's moves.
  40. #define     kClemStepLength    16    // Sets the distance in pixels between Clem the Clam's moves.
  41. #define  kFrontFace            0    // Enumerates the various faces of the clam sprites.
  42. #define  kBlinkFace         1
  43. #define  kEehFace            2
  44. #define  kOohFace            3
  45. #define  kStepRightFace        4
  46. #define  kWalkRightFace        5
  47. #define  kRunRightFace        6
  48. #define  kDizzyRightFace1    7
  49. #define  kDizzyLeftFace1    8
  50. #define  kDizzyRightFace2    9
  51. #define  kDizzyLeftFace2    10
  52. #define  kMaxFaces            11
  53. #define  kBounce            -2    // Sets how many steps the running clam bounces back on impact.
  54. #define  kLastFace        40        // Sets how many frames the clams stay visible after impact.
  55.         
  56.                 // The resource constants--with 'r' prefix like Apple wants them.
  57. #define  rJaneFacesID    136        // The 'PICT' ID# where the views of Jane are located.
  58. #define  rClemFacesID    135        // The 'PICT' ID# where the views of Clem are located.
  59. #define  rMasksID        130        // The 'PICT' ID# where the clam masks are located.
  60. #define  rBackgroundID    134        // The 'PICT' ID# where the background picture is located.
  61. #define  rMainWindowID    128        // The 'WIND' resource ID# for the main window.
  62.  
  63. #define  rHelloSndID    3000
  64. #define  rFootstepSndID    3001
  65. #define  rImpactSndID    3002
  66. #define  rDizzySndID    3003
  67. #define  rDown1SndID    4001
  68. #define  rDown2SndID    4002
  69. #define  rMedium1SndID    4003
  70. #define  rMedium2SndID    4004
  71. #define  rUp1SndID        4005
  72. #define  rUp2SndID        4006
  73. #define  rFade1SndID    4007
  74.  
  75. #define  kColorBitsPreferred    8
  76.     
  77. typedef struct
  78. {
  79.     Rect    face;
  80.     Rect    mask;
  81. } tSpriteType;
  82.  
  83.  
  84. Rect    bigPictureRect, masksRect,  allComboRect;
  85. Rect    janeFacesRect, janeIsAtRect, janeWasAtRect, janeComboRect;
  86. Rect    clemFacesRect, clemIsAtRect, clemWasAtRect, clemComboRect;
  87. CGrafPtr    workCPort, janeFacesCPort, clemFacesCPort, backgroundCPort;
  88. GrafPtr mainWindow, masksPort;
  89. Boolean    itWorked, contactFlag, impactReadyFlag, gameOverFlag, evenFrame;    // Note new flags.
  90. long    targetTick;
  91. short    janeSprite, clemSprite, thisFaceCounter;
  92.  
  93. tSpriteType    sprite[kMaxFaces];
  94.  
  95. extern    Boolean        gUserWantsSound;
  96.     
  97.     
  98. //==============================================================  Prototypes
  99.  
  100. void InitAll(void);
  101. void OpenMainWindow (void);
  102. void SetTheRects(void);
  103. void SetTheCPorts(void);
  104. void CopyBothAtOnce (void);
  105. void CopyOneAtATime (void);
  106. void ShowClams (void);
  107. void DoDelay (void);
  108. void JaneLoop (void);
  109. void ClemLoop (void);
  110. void JaneSpeaks (void);
  111. void DoImpact (void);
  112. void DoBackgroundMusic0(void);
  113. void DoBackgroundMusic1 (void);
  114. void DoBackgroundMusic2 (void);
  115. void DoBackgroundMusic3 (void);
  116. void DoBackgroundFadeOut (void);
  117. void DoBackgroundMusic (void);
  118.  
  119. //==============================================================  Functions
  120.  
  121. //--------------------------------------------------------------  InitAll
  122.  
  123. void InitAll(void)
  124. {
  125.     InitToolbox();
  126.     if (WhatsOurDepth() < kColorBitsPreferred)    // Compare color depth with what we want.
  127.         YellowAlert(kPref8BitColor);            // If smaller, notify user.
  128.     if (WhatsOurDepth() > kColorBitsPreferred)    // Compare color depth with what we want.
  129.         YellowAlert(kPrefDownTo8BitColor);        // If larger, notify user.
  130.     gUserWantsSound = TRUE;
  131.     InitializeForSound();
  132.     LoadARangeOfSounds( rDown1SndID,  rFade1SndID);
  133.     SetTheRects();        // Since some of these Rects define fields in CGrafPorts,…
  134.     SetTheCPorts();        // …set the rects before setting the ports.
  135.     janeSprite = kStepRightFace;
  136.     clemSprite = kRunRightFace;
  137.     thisFaceCounter = 0;
  138.     contactFlag = FALSE;        // Not touching,
  139.     impactReadyFlag = FALSE;    // Not about to collide,
  140.     gameOverFlag = FALSE;        // Not done playing.
  141.     evenFrame = TRUE;
  142.     targetTick = TickCount() + kWaitTicks;
  143.     HideCursor();        // This demo doesn't use mouse input, so why look at it?
  144.     //PlayASound(rFootstepSndID, kLowSoundPriority);        //The first sound played has a brief delay.
  145.  
  146. }
  147.  
  148. //--------------------------------------------------------------  OpenMainWindow
  149.  
  150. void OpenMainWindow (void)
  151. {
  152.     mainWindow = GetNewCWindow(128, 0L, kPutInFront);    // Load window from resource.
  153.     ShowWindow((GrafPtr)mainWindow);                    // Now display it.
  154.     SetPort((GrafPtr)mainWindow);                        // Make its port current.
  155.     ClipRect(&bigPictureRect);                            // Set its clip region.
  156.     CopyRgn(mainWindow->clipRgn, mainWindow->visRgn);    // Set its visRgn.
  157.     ForeColor(blackColor);                                // Set its pen color to black.
  158.     BackColor(whiteColor);                                // Set background color white.
  159. }
  160.  
  161. //--------------------------------------------------------------  SetTheRects
  162.  
  163. void SetTheRects(void)    // The most tedious part of programming this type of game.
  164. {
  165.     SetRect(&janeFacesRect, 0, 0, 448, 64);        // Size and shape of BitMap for the sprite faces.
  166.     SetRect(&clemFacesRect, 0, 0, 448, 64);        // Size and shape of BitMap for the sprite faces.
  167.     SetRect(&masksRect, 0, 0, 448, 32);        // Size and shape of BitMap for the sprite masks.
  168.     SetRect(&bigPictureRect, 0, 0, 512, 322);    // The shape of the picture we'll put in the main window, workCPort and backgroundCPort.}
  169.     SetRect(&janeIsAtRect, 80, 240, 112, 272);    // The shape (32 x 32) of the images of Jane, and the position of the first image.}
  170.     janeWasAtRect = janeIsAtRect;                // Initializing janeIsAtRect...it has to start somewhere, and this is handy.}
  171.     janeComboRect = janeIsAtRect;
  172.     SetRect(&clemIsAtRect, 40, 244, 72, 276);    // The shape (32 x 32) of the images of Clem, and the position of the first image.}
  173.     clemWasAtRect = clemIsAtRect;                // Initializing clemIsAtRect...it has to start somewhere, and this is handy.}
  174.     clemComboRect = clemIsAtRect;
  175.         // And now, the tedium. In this sample, all we're doing is showing the clam running across the screen to the right.}
  176.         // However, if you use ResEdit and look at 'PICT' 129 in Sample.rsrc, you'll find 28 different views of the clam.}
  177.         // If we wanted the clam to run left too, and walk slowly, and face the user, and blink its eyes, we'd be calling…}
  178.         // …SetRect 56 times--one face and one mask per sprite. And if we had jumping clams and rear views of clams…}
  179.         // …and starfish and clamdiggers and other hazards of the clam environment, we might have hundreds of rects to set.}
  180.     SetRect(&sprite[kFrontFace].face, 320, 32, 352, 64);    // The shape and position of sprite[kFrontFace].face on facesCPort.portPixMap.
  181.     SetRect(&sprite[kFrontFace].mask, 320, 0, 352, 32);    // The shape and position of sprite[kFrontFace].mask on masksPort.portPixMap.
  182.     SetRect(&sprite[kBlinkFace].face, 320, 0, 352, 32);    // Note that some faces (e.g. eyes open or closed) use the same mask,…
  183.     SetRect(&sprite[kBlinkFace].mask, 320, 0, 352, 32);    // …since they have the same silhouette.}
  184.     SetRect(&sprite[kEehFace].face, 352, 0, 384, 32);    // I could write more comments here, but setting these rects…
  185.     SetRect(&sprite[kEehFace].mask, 352, 0, 384, 32);    // …is already tedious enough without a bunch of busy-work.
  186.     SetRect(&sprite[kOohFace].face, 352, 32, 384, 64);
  187.     SetRect(&sprite[kOohFace].mask, 352, 0, 384, 32);    
  188.     SetRect(&sprite[kStepRightFace].face, 192, 0, 224, 32);    
  189.     SetRect(&sprite[kStepRightFace].mask, 192, 0, 224, 32);    
  190.     SetRect(&sprite[kWalkRightFace].face, 224, 0, 256, 32);    
  191.     SetRect(&sprite[kWalkRightFace].mask, 224, 0, 256, 32);    
  192.     SetRect(&sprite[kRunRightFace].face, 160, 0, 192, 32);    // BTW, there are plenty more clam faces and masks in the 'PICT's,…
  193.     SetRect(&sprite[kRunRightFace].mask, 160, 0, 192, 32);    // …if you feel you need rect setting practice.  :-)
  194.     SetRect(&sprite[kDizzyRightFace1].face, 384, 0, 416, 32);        // Hey look! Here's more now!
  195.     SetRect(&sprite[kDizzyRightFace1].mask, 384, 0, 416, 32);    
  196.     SetRect(&sprite[kDizzyRightFace2].face, 384, 32, 416, 64);    
  197.     SetRect(&sprite[kDizzyRightFace2].mask, 384, 0, 416, 32);    
  198.     SetRect(&sprite[kDizzyLeftFace1].face, 416, 0, 448, 32);    
  199.     SetRect(&sprite[kDizzyLeftFace1].mask, 416, 0, 448, 32);    
  200.     SetRect(&sprite[kDizzyLeftFace2].face, 416, 32, 448, 64);    
  201.     SetRect(&sprite[kDizzyLeftFace2].mask, 416, 0, 448, 32);    
  202.     
  203. }
  204.  
  205. //--------------------------------------------------------------  SetTheCPorts
  206.  
  207. void SetTheCPorts(void)    // Create the CGrafPorts and load their .portPixMap fields.
  208. {
  209.             // Create BitMap for sprite masks. NOTE THIS IS A BITMAP!
  210.     CreateOffScreenBitMap (&masksRect, &masksPort);
  211.     LoadGraphic (rMasksID);        // …load 'PICT' resource for the clam masks.
  212.     
  213.             // Create PixMap for Jane faces.
  214.     CreateOffScreenPixMap (&janeFacesRect, &janeFacesCPort);
  215.     LoadGraphic (rJaneFacesID);        // …load 'PICT' resource for the clam faces.
  216.  
  217.             // Create PixMap for Clem faces.
  218.     CreateOffScreenPixMap (&clemFacesRect, &clemFacesCPort);
  219.     LoadGraphic (rClemFacesID);        // …load 'PICT' resource for the clam faces.
  220.  
  221.             // Create PixMap for the background.
  222.     CreateOffScreenPixMap (&bigPictureRect, &backgroundCPort);
  223.     LoadGraphic(rBackgroundID);    // …load 'PICT' resource for the background picture.
  224.     
  225.             // Create PixMap for offscreen graphics work.
  226.     CreateOffScreenPixMap (&bigPictureRect, &workCPort);
  227.  
  228.     OpenMainWindow();
  229.  
  230.         //{This fills the main window with the background picture, so the user can see it.
  231.     CopyBits(&((GrafPtr)backgroundCPort)->portBits,
  232.         &((GrafPtr)mainWindow)->portBits, 
  233.         &bigPictureRect, &bigPictureRect, srcCopy, mainWindow->visRgn);
  234.  
  235. // This fills the workCPort.portPixMap with the background picture, so updates can be done quickly.
  236.     CopyBits(&((GrafPtr)backgroundCPort)->portBits,
  237.         &((GrafPtr)workCPort)->portBits, 
  238.         &bigPictureRect, &bigPictureRect, srcCopy, mainWindow->visRgn);
  239. }
  240.  
  241. //--------------------------------------------------------------  CopyBothAtOnce
  242.  
  243. void CopyBothAtOnce (void)    //Display the clams on the screen when they're close together.
  244. {
  245.         //UnionRect(clemComboRect, larryComboRect, allComboRect);
  246.         //{Find the smallest rectangle which will cover Larry and Clem.}
  247.     UnionRect(&janeComboRect, &clemComboRect, &allComboRect);
  248. // Find the smallest rectangle which will cover the old position of Clem and the new.
  249.         //CopyBits(BitMapPtr(workMapC^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, allComboRect, allComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
  250.     CopyBits(&((GrafPtr)workCPort)->portBits, 
  251.         &(((GrafPtr)mainWindow)->portBits), 
  252.         &allComboRect, &allComboRect, srcCopy, mainWindow->visRgn);
  253.         //CopyBits(BitMapPtr(backgroundMapC^.portPixMap^)^, BitMapPtr(workMapC^.portPixMap^)^, allComboRect, allComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
  254.         //{Restore the workPort by covering up our clams with the background they obscure.  This way, workPort is…}
  255.     CopyBits(&((GrafPtr)backgroundCPort)->portBits, 
  256.         &(((GrafPtr)workCPort)->portBits), 
  257.         &allComboRect, &allComboRect, srcCopy, mainWindow->visRgn);
  258. // Restore the workCPort by covering up our clam with the background it obscures.
  259. // This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
  260. // without having to copy the entire PixMap.
  261. }
  262.  
  263. //--------------------------------------------------------------  CopyOneAtATime
  264.  
  265. void CopyOneAtATime (void)    // Display the clams on the screen when they're far apart.
  266. {
  267.         //CopyBits(BitMapPtr(workMapC^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, larryComboRect, larryComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
  268.     CopyBits(&((GrafPtr)workCPort)->portBits, 
  269.         &(((GrafPtr)mainWindow)->portBits), 
  270.         &janeComboRect, &janeComboRect, srcCopy, mainWindow->visRgn);
  271. // Copy the contents of janeComboRect from workCPort->portPixMap to the main window. In one swell foop, old Jane…
  272. //…will be erased, and the new Jane overlayed onto the background picture. Wallah! Flicker-free animation!
  273.     //CopyBits(BitMapPtr(workMapC^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, clemComboRect, clemComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
  274.     CopyBits(&((GrafPtr)workCPort)->portBits, 
  275.         &(((GrafPtr)mainWindow)->portBits), 
  276.         &clemComboRect, &clemComboRect, srcCopy, mainWindow->visRgn);
  277. // Copy the contents of clemComboRect from workCPort->portPixMap to the main window. In one swell foop, old Clem
  278. //…will be erased, and the new Clem overlayed onto the background picture. Wallah! Flicker-free animation!
  279.     //CopyBits(BitMapPtr(backgroundMapC^.portPixMap^)^, BitMapPtr(workMapC^.portPixMap^)^, larryRect, larryRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
  280.     CopyBits(&((GrafPtr)backgroundCPort)->portBits, 
  281.         &(((GrafPtr)workCPort)->portBits), 
  282.         &janeIsAtRect, &janeIsAtRect, srcCopy, mainWindow->visRgn);
  283. // Restore the workCPort by covering up Jane's image with the background it obscures.
  284. // This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
  285. // without having to copy the entire PixMap.
  286.     CopyBits(&((GrafPtr)backgroundCPort)->portBits, 
  287.         &(((GrafPtr)workCPort)->portBits), 
  288.         &clemIsAtRect, &clemIsAtRect, srcCopy, mainWindow->visRgn);
  289. // Restore the workCPort by covering up Clem's image with the background it obscures.
  290. // This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
  291. // without having to copy the entire PixMap.
  292.         //CopyBits(BitMapPtr(backgroundMapC^.portPixMap^)^, BitMapPtr(workMapC^.portPixMap^)^, clemRect, clemRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
  293. }
  294.  
  295. //--------------------------------------------------------------  ShowClam 
  296.  
  297. void ShowClams (void)    // Do the animation and make it appear on the screen.
  298. {
  299.     Rect dummyRect;
  300.     
  301.     CopyMask(&((GrafPtr)janeFacesCPort)->portBits, 
  302.         &((GrafPtr)masksPort)->portBits, 
  303.         &((GrafPtr)workCPort)->portBits, 
  304.         &sprite[janeSprite].face, 
  305.         &sprite[janeSprite].mask, 
  306.         &janeIsAtRect);
  307. // Now there is an image of a clam in the new position in workMap.  If we had done this work in…
  308. // mainWindow, we would have seen considerable flickering.  Instead, we did it offscreen, and left the…
  309. // previous image of the clam visible on the screen while we worked.
  310.  
  311.     UnionRect(&janeWasAtRect, &janeIsAtRect, &janeComboRect);
  312. // Find the smallest rectangle which will cover the old position of Jane and the new.
  313.  
  314. CopyMask(&((GrafPtr)clemFacesCPort)->portBits, 
  315.         &((GrafPtr)masksPort)->portBits, 
  316.         &((GrafPtr)workCPort)->portBits, 
  317.         &sprite[clemSprite].face, 
  318.         &sprite[clemSprite].mask, 
  319.         &clemIsAtRect);
  320. // Now there is an image of a clam in the new position in workMap.  If we had done this work in…
  321. // mainWindow, we would have seen considerable flickering.  Instead, we did it offscreen, and left the…
  322. // previous image of the clam visible on the screen while we worked.
  323.  
  324.     UnionRect(&clemWasAtRect, &clemIsAtRect, &clemComboRect);
  325. // Find the smallest rectangle which will cover the old position of Clem and the new.
  326.  
  327.  
  328.     if (SectRect(&clemIsAtRect, &janeIsAtRect, &dummyRect))
  329.     {
  330.         contactFlag = TRUE;
  331.         CopyBothAtOnce();
  332.     }
  333.     else
  334.     {
  335.         contactFlag = FALSE;
  336.         CopyOneAtATime();
  337.     }
  338. }
  339. //    CopyBits(&((GrafPtr)workCPort)->portBits, 
  340.         //&(((GrafPtr)mainWindow)->portBits), 
  341.         //&clamComboRect, &clamComboRect, srcCopy, mainWindow->visRgn);
  342. // Copy the contents of comboRect from workCPort->portPixMap to the main window. In one swell foop, the old clam…}
  343. //…will be erased, and the new clam overlayed onto the background picture. Wallah! Flicker-free animation!}
  344.  
  345.     //CopyBits(&((GrafPtr)backgroundCPort)->portBits, 
  346.         //&(((GrafPtr)workCPort)->portBits), 
  347.         //&clamIsAtRect, &clamIsAtRect, srcCopy, mainWindow->visRgn);
  348. // Restore the workCPort by covering up our clam with the background it obscures.
  349. // This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
  350. // without having to copy the entire PixMap.
  351. //}
  352.  
  353. //--------------------------------------------------------------  DoDelay
  354.  
  355. // This is the companion function to the above function (LogNextTick()).
  356. // We do nothing but loop until TickCount() catches up with (or passes) our…
  357. // global variable tickNext.
  358.  
  359. void DoDelay (void)
  360. {
  361.     do
  362.     {
  363.     }
  364.     while (TickCount() < targetTick);            // Loop until TickCount() catches up.
  365.     targetTick = TickCount() + kWaitTicks;
  366. }
  367.  
  368. //--------------------------------------------------------------  JaneLoop
  369.  
  370. void JaneLoop (void)
  371. {
  372.     switch    (janeSprite)                    //If the current view of jane is…
  373.     {    case    (kStepRightFace):             // …kStepRightFace, then set thisSprite to…
  374.         {    janeSprite = kWalkRightFace;    // …kWalkRightFace, and if it is currently…
  375.             break;    }
  376.         case    (kWalkRightFace):             // …kWalkFace, then set it to…
  377.         {    janeSprite = kRunRightFace;        // …kRunRightFace.
  378.             break;    }
  379.     // And if it was neither kStepRightFace nor kWalkRightFace, then janeSprite was either…
  380.         default                    :             // …kRunRightFace, or what it was when RunRight()…
  381.             janeSprite = kStepRightFace;    // …was called, so we set it to kStepRightFace
  382.     }
  383.     
  384.     janeWasAtRect = janeIsAtRect;            // Store the clam's current position as its last position,…
  385.                                             // …we'll be erasing it next time through the loop.
  386.     OffsetRect(&janeIsAtRect, kJaneStepLength, 0);    // Set the clam's next position--it'll be…
  387.                                             // …kStepLength pixels to the right of its last position.
  388.     if (janeIsAtRect.left > 512)                // If the clam has wandered out of sight,…
  389.     {                                        // …set the right border of clamIsAtRect…
  390.         janeIsAtRect.right = 0;                // …to the left edge of the screen…
  391.         janeIsAtRect.left = -32;            // …and move the left border of clamIsAtRect…
  392.     }                                        // …as needed to maintain its 32 x 32 shape & size.
  393. }
  394.  
  395. //--------------------------------------------------------------  ClemLoop
  396.  
  397. void ClemLoop (void)
  398. {
  399.     switch    (clemSprite)                    //If the current view of Clem is…
  400.     {    case    (kStepRightFace):             // …kStepRightFace, then set thisSprite to…
  401.         {    clemSprite = kWalkRightFace;    // …kWalkRightFace, and if it is currently…
  402.             break;    }
  403.         case    (kWalkRightFace):             // …kWalkFace, then set it to…
  404.         {    clemSprite = kRunRightFace;        // …kRunRightFace.
  405.             break;    }
  406.     // And if it was neither kStepRightFace nor kWalkRightFace, then clemSprite was either…
  407.         default                    :             // …kRunRightFace, or what it was when RunRight()…
  408.             clemSprite = kStepRightFace;    // …was called, so we set it to kStepRightFace
  409.     }
  410.     clemWasAtRect = clemIsAtRect;            // Store the clam's current position as its last position,…
  411.                                             // …we'll be erasing it next time through the loop.
  412.     OffsetRect(&clemIsAtRect, kClemStepLength, 0);    // Set the clam's next position--it'll be…
  413.                                             // …kStepLength pixels to the right of its last position.
  414.     if (clemIsAtRect.left > 512)                // If the clam has wandered out of sight,…
  415.     {                                        // …set the right border of clamIsAtRect…
  416.         clemIsAtRect.right = 0;                // …to the left edge of the screen…
  417.         clemIsAtRect.left = -32;            // …and move the left border of clamIsAtRect…
  418.     }                                        // …as needed to maintain its 32 x 32 shape & size.
  419. //    if (clemSprite == kStepRightFace)                // Only sound a footstep in pose where foot strikes ground.
  420. //          PlayASound(rFootstepSndID, kLowSoundPriority);        //Ahh, the pitter patter of tiny feet.
  421. //    THE LINES ABOVE ARE COMMENTED OUT SO THE FOOTSTEPS WON'T INTERFERE WITH THE MUSIC.
  422. }
  423.  
  424. //--------------------------------------------------------------  JaneSpeaks
  425.  
  426. // This routine has the clam stop moving, face the screen, and move its face.
  427.  
  428. void JaneSpeaks (void)
  429. {    Rect dummyRect;
  430.     if ((impactReadyFlag) && (SectRect(&janeIsAtRect, &clemIsAtRect, &dummyRect)))
  431.         DoImpact();
  432.     thisFaceCounter = thisFaceCounter + 1;
  433.          switch (thisFaceCounter)
  434.          {    case    (1): 
  435.             {    janeSprite = kFrontFace;
  436.                 break;    }
  437.             case    (2): 
  438.             {    janeSprite = kEehFace;
  439.                 break;    }
  440.             case    (3):     // This keeps an impact from occurring when both clams are in the same…
  441.             {    if (!(SectRect(&janeIsAtRect, &clemIsAtRect, &dummyRect)))    // …place when the…
  442.                     impactReadyFlag = TRUE;                                    // …button is pushed.
  443.                 break;    }
  444.             case    (4): 
  445.             {    janeSprite = kFrontFace;
  446.                 break;    }
  447.             case    (5): 
  448.             {    janeSprite = kOohFace;
  449.                 break;    }
  450.             case    (9): 
  451.             {    janeSprite = kEehFace;
  452.                 break;    }
  453.             case    (11): 
  454.             {    janeSprite = kOohFace;
  455.                 break;    }
  456.             case    (13): 
  457.             {    janeSprite = kFrontFace;
  458.                 break;    }
  459.             case    (16): 
  460.             {    janeSprite = kBlinkFace;
  461.                 break;    }
  462.             case    (18): 
  463.             {    janeSprite = kFrontFace;
  464.                 break;    }
  465.             case    (35): 
  466.             {    janeSprite = kBlinkFace;
  467.                 break;    }
  468.             case    (38): 
  469.             {    janeSprite = kFrontFace;
  470.                 break;    }
  471.             case    (39): 
  472.             {    impactReadyFlag = TRUE;
  473.                 break;    }
  474.         }
  475. }
  476.  
  477. //--------------------------------------------------------------  DoImpact
  478.  
  479. void DoImpact (void)
  480. {
  481.     janeWasAtRect = janeIsAtRect;    // Store the clam's current position as its last position.
  482.     OffsetRect(&janeIsAtRect, kJaneStepLength, 0);    // Set the clam's next position.
  483.     clemWasAtRect = clemIsAtRect;        // Store the clam's current position as its last position.
  484.     OffsetRect(&clemIsAtRect, kClemStepLength * kBounce, 0);    // Set the clam's next position.
  485.     PlayASound(rImpactSndID, kHighestSoundPriority);        // High enough to interrupt anything.
  486.     thisFaceCounter = 0;
  487.     while (thisFaceCounter <= kLastFace)
  488.     {
  489.         ShowClams();
  490.         DoDelay();                // Do nothing for a while.
  491.         PlayLoopSound(rDizzySndID, kHighSoundPriority);    // Not high enough to interrupt the impact.
  492.         thisFaceCounter = thisFaceCounter + 1;
  493.         evenFrame = !evenFrame;
  494.         if (evenFrame)
  495.         {
  496.             janeSprite = kDizzyLeftFace1;
  497.             clemSprite = kDizzyRightFace1;
  498.         }
  499.         else
  500.         {
  501.             janeSprite = kDizzyLeftFace2;
  502.             clemSprite = kDizzyRightFace2;
  503.         }
  504.     }
  505.     gameOverFlag = TRUE;        // And we're outta here. Game over.
  506. }
  507.  
  508. //--------------------------------------------------------------  DoBackgroundMusic0
  509.  
  510. void DoBackgroundMusic0 (void)
  511. {
  512.     AddSoundToQ(rFade1SndID);
  513.     AddSoundToQ(rFade1SndID);
  514.     AddSoundToQ(rFade1SndID);
  515.     AddSoundToQ(rFade1SndID);
  516.     AddSoundToQ(rMedium1SndID);
  517.     AddSoundToQ(rUp2SndID);
  518.     AddSoundToQ(rMedium1SndID);
  519.     AddSoundToQ(rMedium2SndID);
  520.     AddSoundToQ(rDown1SndID);
  521.     AddSoundToQ(rMedium1SndID);
  522.     AddSoundToQ(rMedium2SndID);
  523. }
  524.  
  525. //--------------------------------------------------------------  DoBackgroundMusic1
  526.  
  527. void DoBackgroundMusic1 (void)
  528. {
  529.     AddSoundToQ(rUp1SndID);
  530.     AddSoundToQ(rDown2SndID);
  531.     AddSoundToQ(rMedium2SndID);
  532.     AddSoundToQ(rDown1SndID);
  533.     AddSoundToQ(rUp2SndID);
  534.     AddSoundToQ(rMedium1SndID);
  535.     AddSoundToQ(rMedium2SndID);
  536.     AddSoundToQ(rMedium1SndID);
  537. }
  538.  
  539. //--------------------------------------------------------------  DoBackgroundMusic2
  540.  
  541. void DoBackgroundMusic2 (void)
  542. {
  543.     AddSoundToQ(rUp2SndID);
  544.     AddSoundToQ(rMedium1SndID);
  545.     AddSoundToQ(rUp2SndID);
  546.     AddSoundToQ(rUp1SndID);
  547.     AddSoundToQ(rMedium1SndID);
  548.     AddSoundToQ(rMedium2SndID);
  549.     AddSoundToQ(rMedium1SndID);
  550.     AddSoundToQ(rDown1SndID);
  551. }
  552.  
  553. //--------------------------------------------------------------  DoBackgroundMusic3
  554.  
  555. void DoBackgroundMusic3 (void)
  556. {
  557.     AddSoundToQ(rUp2SndID);
  558.     AddSoundToQ(rDown1SndID);
  559.     AddSoundToQ(rMedium1SndID);
  560.     AddSoundToQ(rMedium2SndID);
  561.     AddSoundToQ(rDown2SndID);
  562.     AddSoundToQ(rMedium2SndID);
  563.     AddSoundToQ(rDown1SndID);
  564.     AddSoundToQ(rMedium1SndID);
  565. }
  566.  
  567. //--------------------------------------------------------------  DoBackgroundFadeOut
  568.  
  569. void DoBackgroundFadeOut (void)
  570. {
  571.     AddSoundToQ(rUp2SndID);
  572.     AddSoundToQ(rMedium1SndID);
  573.     AddSoundToQ(rMedium2SndID);
  574.     AddSoundToQ(rUp2SndID);
  575.     AddSoundToQ(rMedium2SndID);
  576.     AddSoundToQ(rMedium2SndID);
  577.     AddSoundToQ(rMedium1SndID);
  578.     AddSoundToQ(rFade1SndID);
  579.     AddSoundToQ(rFade1SndID);
  580.     AddSoundToQ(rFade1SndID);
  581.     AddSoundToQ(rFade1SndID);
  582. }
  583.  
  584. //--------------------------------------------------------------  DoBackgroundMusic
  585.  
  586. void DoBackgroundMusic (void)
  587. {
  588.     DoBackgroundMusic0();
  589.     DoBackgroundMusic1();
  590.     DoBackgroundMusic2();
  591.     DoBackgroundMusic3();
  592.     DoBackgroundMusic2();
  593.     DoBackgroundMusic1();
  594.     DoBackgroundMusic1();
  595.     DoBackgroundMusic2();
  596.     DoBackgroundFadeOut();
  597. }
  598.  
  599. //--------------------------------------------------------------  main
  600. //----------------------------------------------------------------------
  601.  
  602. void main(void)
  603. {
  604.     InitAll();
  605.     DoBackgroundMusic();
  606.         while (!Button())    // Before the user presses the mouse button, nothing happens.
  607.         {
  608.         }
  609.     while (Button())    // When the user presses the mouse button, nothing happens.
  610.         {
  611.         }
  612.     while (!Button())    // When the mouse button is released, continue to…
  613.         {
  614.         ShowClams();    // Put the clams on the screen.
  615.         DoDelay();        // Keep everything from happening too fast.
  616.         JaneLoop();        // Put Jane in her next position.
  617.         ClemLoop();        // Put Clem in his next position.
  618.         }
  619.     PlayASound(rHelloSndID, kMediumSoundPriority);    // Sound, "Hello" when button is pushed.
  620.     while (!(gameOverFlag))    // …until the clams crash into each other and fall down dizzy.
  621.         {    
  622.         ShowClams();    // Put the clams on the screen.
  623.         DoDelay();        // Keep everything from happening too fast.
  624.         JaneSpeaks();    // Make mouth motions, shift into impact mode when ready.
  625.         ClemLoop();        // Put Clem in his next position.
  626.         }
  627.     CloseDownSound();
  628.     InitCursor();    // Rarely needed, since most programs call InitCursor on startup. Still, it's…
  629.                     // a good habit to leave everything in normal condition when your programs quit.
  630. }                    // And we're done.
  631.  
  632. //------------------------------------------------------------------------------------------\\
  633. //                                    End ClamMusic.c                                            \\
  634. //------------------------------------------------------------------------------------------\\
  635.